﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace DataMining
{
    public partial class frmKMeans : Form
    {
        public frmKMeans()
        {
            InitializeComponent();
        }

        List<flowers> arrFlowers = new List<flowers>();

        //brower source file
        private void btnBrowser_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            string _fileName = "";
            string path = "";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                _fileName = System.IO.Path.GetFileName(ofd.FileName);
                path = System.IO.Path.GetDirectoryName(ofd.FileName);
            }
            txtPath.Text = path + "\\" + _fileName;
        }

        //cancel 
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        //load data from file
        public void LoadData(ref List<flowers> a, string path, int attr1, int attr2)
        {
            try
            {
                string data = File.ReadAllText(path);
                string[] List = data.Split(' ');
                foreach (string w in List)
                {
                    string[] word = w.Split(',');
                    flowers f = new flowers();
                    if (word.Count() > 0)
                    {
                        //chi lay nhung gia tri cua thuoc tinh duoc chon
                        if (attr1 == 0 || attr2 == 0)
                        {
                            if (word[0] == "Iris-setosa\n")
                            {
                                f.group = 1;
                            }
                            else if (word[0] == "Iris-versicolor\n")
                            {
                                f.group = 2;
                            }
                            else if (word[0] == "Iris-virginica\n")
                            {
                                f.group = 3;
                            }
                        }
                        else
                        {
                            f.group = 0;
                        }
                        if (attr1 == 1 || attr2 == 1)
                        {
                            f.Petallength = double.Parse(word[1]);
                        }
                        else
                        {
                            f.Petallength = 0;
                        }
                        if (attr1 == 2 || attr2 == 2)
                        {
                            f.Petalwidth = double.Parse(word[2]);
                        }
                        else
                        {
                            f.Petalwidth = 0;
                        }
                        if (attr1 == 3 || attr2 == 3)
                        {
                            f.Sepallength = double.Parse(word[3]);
                        }
                        else
                        {
                            f.Sepallength = 0;
                        }
                        if (attr1 == 4 || attr2 == 4)
                        {
                            f.Sepalwidth = double.Parse(word[4]);
                        }
                        else
                        {
                            f.Sepalwidth = 0;
                        }
                        f.groupIndex = -1;
                    }
                    a.Add(f);
                }
            }
            catch
            {
                MessageBox.Show("Chuong trinh chi co the hoat dong voi IRis Database! Vui long chon lai database IRis");
                return;
            }
        }

        //calculate the distance
        public double Euclidean(flowers f1, flowers f2)
        {
            double d = 0;

            d = Math.Sqrt(Math.Pow((f1.group - f2.group), 2) + Math.Pow((f1.Petallength - f2.Petallength), 2)
                + Math.Pow((f1.Petalwidth - f2.Petalwidth), 2) + Math.Pow((f1.Sepallength - f2.Sepallength), 2) + Math.Pow((f1.Sepalwidth - f2.Sepalwidth), 2));
            return d;
        }

        //find group for node
        public int FindSuitableGroup(flowers f, List<flowers> center)
        {
            int group = -1;
            double dMin = -1;

            for (int i = 0; i < center.Count; i++)
            {
                double d = Euclidean(f, center[i]);
                if (dMin < 0 || d < dMin)
                {
                    dMin = d;
                    group = i;
                }
            }

            return group;
        }

        //Add two attribute
        public void Add(ref flowers ft, flowers f1)
        {
            ft.group = ft.group + f1.group;
            ft.groupIndex = ft.groupIndex + f1.groupIndex;
            ft.Petallength = ft.Petallength + f1.Petallength;
            ft.Petalwidth = ft.Petalwidth + f1.Petalwidth;
            ft.Sepallength = ft.Sepallength + f1.Sepallength;
            ft.Sepalwidth = ft.Sepalwidth + f1.Sepalwidth;
        }

        //calculate average
        public void Avg(int dem, ref flowers ft)
        {
            ft.group = ft.group / dem;
            ft.groupIndex = ft.groupIndex / dem;
            ft.Petallength = ft.Petallength / dem;
            ft.Petalwidth = ft.Petalwidth / dem;
            ft.Sepallength = ft.Sepallength / dem;
            ft.Sepalwidth = ft.Sepalwidth / dem;

        }

        //kmeans
        public void KMeans(List<flowers> a, int k)
        {
            try
            {
                #region Select center random
                List<flowers> centroid = new List<flowers>();
                List<int> listInt = new List<int>();
                //random
                Random r = new Random();
                for (int i = 0; i < k; i++)
                {
                    int y;
                    do
                    {
                        y = r.Next(0, 149);

                    } while (listInt.IndexOf(y) != -1);
                    centroid.Add(a[y]);
                    listInt.Add(y);
                }
                #endregion

                #region Kmeans
                do
                {
                    bool flagChange = false;//co nhan biet co su thay doi nhom khong
                    //Find group
                    foreach (flowers f in a)
                    {
                        int groupIndex = f.groupIndex;
                        int newGroupIndex = FindSuitableGroup(f, centroid);
                        f.groupIndex = newGroupIndex;
                        if (newGroupIndex != groupIndex)
                        {
                            flagChange = true;
                        }
                    }
                    if (!flagChange)
                        break;
                    //Find new centroid

                    for (int j = 0; j < k; j++)
                    {
                        flowers ft = new flowers();
                        int dem = 0;
                        foreach (flowers f in a)
                        {
                            if (f.groupIndex == j)
                            {
                                Add(ref ft, f);
                                dem++;
                            }
                        }
                        if (dem != 0)
                        {
                            Avg(dem, ref ft);
                            centroid[j] = ft;
                        }
                    }
                }
                while (true);
                #endregion


                #region Draw graph
                frmChart frm = new frmChart();
                frm.listFlowers = a;
                frm.numberOfGroup = k;
                frm.ShowDialog();
                #endregion
            }
            catch
            {
                MessageBox.Show("Co loi, vui long thuc hien lai");
            }
        }

        //Bat dau fan cum
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (txtPath.Text != "" && cmbNumberOfGroups.Text != "" && int.Parse(cmbNumberOfGroups.Text) < 11 && int.Parse(cmbNumberOfGroups.Text) > 0)
            {
                if (CheckNumberOfSelection())
                {

                    int attribute1 = -1, attribute2 = -1;
                    GetInformationOfCheckbox(ref attribute1, ref attribute2);

                    //Tao danh sach cac bong hoa
                    List<flowers> f = new List<flowers>();
                    try
                    {
                        LoadData(ref f, txtPath.Text, attribute1, attribute2);

                        //goi ham phan cum k-means
                        KMeans(f, int.Parse(cmbNumberOfGroups.Text));
                    }
                    catch
                    {
                        txtPath.Text = "";
                        if (chkClass.Checked == true)
                            chkClass.Checked = false;
                        if (chkPetallength.Checked == true)
                            chkPetallength.Checked = false;
                        if (chkPetalwidth.Checked == true)
                            chkPetalwidth.Checked = false;
                        if (chkSepallength.Checked == true)
                            chkSepallength.Checked = false;
                        if (chkSepalwidth.Checked == true)
                            chkSepalwidth.Checked = false;
                        cmbNumberOfGroups.SelectedIndex = -1;
                        return;
                    }

                }
                else
                {
                    MessageBox.Show("Chi duoc chon dung 2 thuoc tinh! Vui long chon lai");
                    return;
                }
            }
            else
            {
                MessageBox.Show("Duong dan hoac so nhom chua hop le");
                return;
            }
        }

        //kiem tra so luong check cua nguoi dung
        public bool CheckNumberOfSelection()
        {
            int number = 0;
            if (chkClass.Checked == true)
                number++;
            if (chkPetalwidth.Checked == true)
                number++;
            if (chkSepallength.Checked == true)
                number++;
            if (chkSepalwidth.Checked == true)
                number++;
            if (chkPetallength.Checked == true)
                number++;
            if (number == 2)
                return true;
            else
                return false;
        }

        //lay thong tin vi tri cac thuoc tinh
        public void GetInformationOfCheckbox(ref int firstAttribute, ref int secondAttribute)
        {
            firstAttribute = -1;
            secondAttribute = -1;

            if (chkClass.Checked == true)
            {
                if (firstAttribute == -1)
                    firstAttribute = 0;
                else
                {
                    secondAttribute = 0;
                    return;
                }
            }
            if (chkPetallength.Checked == true)
            {
                if (firstAttribute == -1)
                    firstAttribute = 1;
                else
                {
                    secondAttribute = 1;
                    return;
                }
            }
            if (chkPetalwidth.Checked == true)
            {
                if (firstAttribute == -1)
                    firstAttribute = 2;
                else
                {
                    secondAttribute = 2;
                    return;
                }
            }
            if (chkSepallength.Checked == true)
            {
                if (firstAttribute == -1)
                    firstAttribute = 3;
                else
                {
                    secondAttribute = 3;
                    return;
                }
            }
            if (chkSepalwidth.Checked == true)
            {
                if (firstAttribute == -1)
                    firstAttribute = 4;
                else
                {
                    secondAttribute = 4;
                    return;
                }
            }
            if (firstAttribute == secondAttribute)
            {
                MessageBox.Show("Loi chon thuoc tinh!");
                return;
            }

        }

    }
}
